﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace VeryGoodSync
{
    class JobWorker
    {
        private readonly List<ISyncProvider> _syncProviders = new List<ISyncProvider>();
        private readonly int _delay;
        private readonly string _source;
        private readonly string _name;
        private FileSystemWatcher _watcher;

        private SetTimeout _delayTimer;

        public JobWorker(VeryGoodJob job)
        {
            if (!Directory.Exists(job.Source)) Directory.CreateDirectory(job.Source);
            _source = job.Source;
            _delay = job.Delay;
            _name = job.Name;

            foreach (var plugin in job.Plugins)
            {
                try
                {
                    if (!(Activator.CreateInstance(plugin.Type) is ISyncProvider p)) continue;
                    p.Init(plugin.Arguments);
                    _syncProviders.Add(p);
                }
                catch (Exception ex)
                {
                    Ui.TraceError($"{job.Name}初始化插件出错", ex);
                }
            }

            ReStart();
        }

        void ReStart()
        {
            Log.WriteMessage($"{_name} 监控正在启动..");
            _watcher?.Dispose();
            _watcher = new FileSystemWatcher(_source, "*.*")
            {
                NotifyFilter = NotifyFilters.LastWrite,
                IncludeSubdirectories = true
            };
            _watcher.Changed += _watcher_Changed;
            _watcher.Created += _watcher_Created;
            _watcher.Deleted += _watcher_Deleted;
            _watcher.Renamed += _watcher_Renamed;
            _watcher.Error += _watcher_Error;
            _watcher.EnableRaisingEvents = true;

            DoSync();
        }

        private void _watcher_Error(object sender, ErrorEventArgs e)
        {
            Log.WriteMessage($"{_name} 监控出错 {e.GetException().Message} 5秒后重启..");
            SetTimeout.New(5000, ReStart);
        }

        private void _watcher_Renamed(object sender, RenamedEventArgs e)
        {
            DoSync();
        }

        private void _watcher_Deleted(object sender, FileSystemEventArgs e)
        {
            DoSync();
        }

        private void _watcher_Created(object sender, FileSystemEventArgs e)
        {
            DoSync();
        }

        private void _watcher_Changed(object sender, FileSystemEventArgs e)
        {
            DoSync();
        }

        public void DoSync()
        {
            _delayTimer?.Cancel();
            if (_delay == 0)
            {
                InvokeSyncProvider();
            }
            else
            {
                _delayTimer = SetTimeout.New(_delay * 1000, InvokeSyncProvider);
            }
        }

        void InvokeSyncProvider()
        {
            if (IsPaused) return;
            var task = new List<Task>();
            Ui.StartAnimation();
            Ui.ShowInfo($"[{_name}]正在同步...");
            foreach (var provider in _syncProviders)
            {
                task.Add(Task.Factory.StartNew(() =>
                {
                    try
                    {
                        provider.Sync(_source);
                        Log.WriteMessage($"{_name} {provider.GetType().Name} 执行成功.");
                    }
                    catch (Exception ex)
                    {
                        Thread.Sleep(1000);
                        Ui.TraceError($"{_name}执行出错", ex);
                    }
                }));
            }

            Task.WaitAll(task.ToArray());

            Ui.StopAnimation();
            Ui.ShowSuccess($"[{_name}]同步成功.");
        }

        /// <summary>
        /// 下班
        /// </summary>
        public void KnockOff()
        {
            _watcher.Dispose();
            foreach (var provider in _syncProviders)
            {
                try
                {
                    provider.Kill();
                }
                catch (Exception ex)
                {
                    Ui.TraceError("释放同步程序", ex);
                }
            }
        }

        /// <summary>
        /// 是否暂停
        /// </summary>
        public bool IsPaused { get; set; }
    }
}
